package cn.zhxu.research;

import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;

public class CorrelationAnalysis {

    static final int LEVEL_0 = 2812;
    static final int LEVEL_1 = 2494 + LEVEL_0;
    static final int LEVEL_2 = 2822 + LEVEL_1;
    static final int LEVEL_3 = 4192 + LEVEL_2;
    static final int LEVEL_4 = 2954 + LEVEL_3;
    static final int LEVEL_5 = 802 + LEVEL_4;

    public static void main(String[] args) throws IOException {
//        System.out.println(LEVEL_5);
//        calculateLevel();
        doAnalysis();
    }

    private static void doAnalysis() throws IOException {
        System.out.println("模型名称|余弦指标|距离指标");
        System.out.println("-|-|-");
        for (String modelId : Models.models) {
            var items = Result.readDataItems("E:/SpaceMine/research/data/models/" + modelId + ".txt");
            var r1 = calculatePearson(items, Result::getCosine, Result::setCScore, Result::getCScore, false);
            var r2 = calculatePearson(items, r -> -r.getDistance(), Result::setDScore, Result::getDScore, true);
            System.out.println(modelId + "|" + r1 + "|" + r2);
            for (int i = 0; i < items.size(); i++) {
                var item = items.get(i);
                if (item.getCScore() != item.getDScore()) {
                    System.out.println("Index: " + i + ": " + item);
                }
            }
            break;
        }
    }

    private static double calculatePearson(
            List<Result> list,
            Function<Result, Float> compareKey,
            BiConsumer<Result, Integer> scoreSetter,
            Function<Result, Integer> scoreGetter,
            boolean check
    ) {
        var items = list.stream().sorted(Comparator.comparing(compareKey)).toList();
        int n = items.size();
        for (int i = 0; i < n; i++) {
            var item = items.get(i);
            if (i < LEVEL_0) {
                scoreSetter.accept(item, 0);
            } else if (i < LEVEL_1) {
                scoreSetter.accept(item, 1);
            } else if (i < LEVEL_2) {
                scoreSetter.accept(item, 2);
            } else if (i < LEVEL_3) {
                scoreSetter.accept(item, 3);
            } else if (i < LEVEL_4) {
                scoreSetter.accept(item, 4);
            } else if (i < LEVEL_5) {
                scoreSetter.accept(item, 5);
            }
            if (check) {
                if (i != item.getIdx()) {
                    System.out.println(i + " - " + item);
                }
            } else {
                item.setIdx(i);
            }
            if (check && item.getCScore() != item.getDScore()) {
                System.out.println(item);
            }
        }
        long sumXY = 0;
        long sumX = 0;
        long sumY = 0;
        long sumX2 = 0;
        long sumY2 = 0;
        for (var item : items) {
            int x = item.getScore();
            int y = scoreGetter.apply(item);
            sumX += x;
            sumY += y;
            sumXY += (long) x * y;
            sumX2 += (long) x * x;
            sumY2 += (long) y * y;
        }
        return  (n * sumXY - sumX * sumY) /
                Math.sqrt((n * sumX2 - sumX * sumX) * (n * sumY2 - sumY * sumY));
    }

    static void calculateLevel() throws IOException {
        int level0 = 0;
        int level1 = 0;
        int level2 = 0;
        int level3 = 0;
        int level4 = 0;
        int level5 = 0;
        int levelx = 0;
        var items = DataItem.readDataItems("E:/SpaceMine/research/data/dataset.txt");
        for (var item: items) {
            var score = item.getScore();
            if (score == 0) {
                level0++;
            } else if (score == 1) {
                level1++;
            } else if (score == 2) {
                level2++;
            } else if (score == 3) {
                level3++;
            } else if (score == 4) {
                level4++;
            } else if (score == 5) {
                level5++;
            } else {
                System.out.println(item);
                levelx++;
            }
        }
        System.out.println("level0: " + level0);
        System.out.println("level1: " + level1);
        System.out.println("level2: " + level2);
        System.out.println("level3: " + level3);
        System.out.println("level4: " + level4);
        System.out.println("level5: " + level5);
        System.out.println("levelx: " + levelx);
    }

}
